Implement nelements for various backends

Allows differentiation between `expr.count()` (will eventually ignore `NA`
values) and `expr.nelements()` (never ignores `NA` values).

Also adds an `nrows` property of symbols
I don't have any particular thoughts on ideal use cases here.  I'm just trying to make things consistent with other reductions like `sum` and `mean`.  Actually, if you're inheriting from `Reduction` then the dshape is already set for you to be non-scalar in these cases.

In this case I guess `t.nelements(axis=(0, 1))` means for each subspace/slice of my dataset that starts out `data[:, :, ` please give me the number of elements in that slice.  So in the 3d case this is something like 

    [data[:, :, i].numel for i in range(data.shape[2])]