Add more array expressions.

Add `TensorDot` and `Transpose` expressions.  Also fix shape handling and enforce dshape validation on binary operators.

```Python
In [1]: from blaze import *

In [2]: x = symbol('x', '10 * 20 * int')

In [3]: y = symbol('y', '20 * 30 * int')
In [4]: x + y
ValueError: Shapes don't align, (10, 20)

In [5]: x.dot(y)
tensordot(x, y)

In [6]: y.T
transpose(y)
```
Hrm, oddly NumPy disagrees with this.

```Python
In [1]: from blaze import *

In [2]: x = np.empty(shape=(3, 5), dtype=bool)

In [3]: x
Out[3]: 
array([[ True,  True,  True,  True,  True],
       [ True, False, False,  True,  True],
       [ True,  True, False, False, False]], dtype=bool)

In [4]: x.dot(x.T)
Out[4]: 
array([[ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True]], dtype=bool)
```