Fixing Broadcast

Reimplement `Broadcast` operation for fusing scalar expressions over collections.

## Broadcast docstring

```Python
    """ Fuse scalar expressions over collections

    Given elementwise operations on collections, e.g.

    >>> a = Symbol('a', '100 * int')
    >>> t = Symbol('t', '100 * {x: int, y: int}')

    >>> expr = sin(a) + t.y**2

    It may be best to represent this as a scalar expression mapped over a
    collection

    >>> sa = Symbol('a', 'int')
    >>> st = Symbol('t', '{x: int, y: int}')

    >>> sexpr = sin(sa) + st.y**2

    >>> expr = Broadcast((a, t), (sa, st), sexpr)

    This provides opportunities for optimized computation.

    In practice, expressions are often collected into Broadcast expressions
    automatically.  This class is mainly intented for internal use.
```

## Optimization issues

Generally we don't construct `Broadcast`s by hand.  Instead, there are a few scattered functions to collect up operations of various types automatically using the somewhat new-and-experimental `optimize` framework.  There are a few of these due to slight differences in how the backends want operations bundled up.  Probably this should be cleaned up a bit.
might be useful to have a message here