More WorkflowOp debugging improvements

- RenderTree.diff now reflects node type changes
- RenderTree.diff output more readable
- properly indent for multi-line labels (i.e. JavaScript)
- render SingleSourceOps as a flat list under a "Chain" node
- less amiguous labels for projections
- foldLeftOp takes varargs instead of a NEL
- a little more coverage
@sellout: the signature of FoldLeftTask requires all the tasks except the first to be MapReduceTasks. Right now (in my workspace) FoldLeftOp looks like `case class FoldLeftOp private (head: WorkflowOp, tail: NonEmptyList[WorkflowOp])`. There is (and was already) a hackish runtime check that all the ops except the first crush to MapReduceTasks.

I can change the type of `tail` to `NonEmptyList[MapReducishOp]` if introduce a trait for that, but I don't we want to, because the right thing to do here is to crush and then if necessary generate an extra MapReduceTask to merge the result, right? So I think I'll leave it as is for now.