Optimize framework

How do we build backend specific optimizations on expressions?

Given some expression and some data we might want to manipulate the expression prior to entering the `compute` interpreter chain.  These manipulations/optimizations might be backend specific.  To that end I propose a new dispatched function

```Python
@dispatch(Expr, BackendData)
def optimize(expr, data):
    return new_expr
```

Immediately this has implications for bcolz and #740 

Open question - how do we do optimizations when we have a few different data resources?

This also includes a variety of small organizational fixes discovered while digging into `compute/core.py`

cc @cpcloud 
I'm unfamiliar with the term *splat operator*.

The default `optimize` function above takes two.  In principle an expression may have more than one leaf, (e.g. any expression that contains a `Join`) in such cases we might have (admittedly fairly specialized) `optimize` implementations for `Expr, SQL, SQL` for example.  

Though in general I'm not entirely sure how best to handle optimizations on expressions with many data resources (see open question at the top of the PR.)