Scenegraph optimizations

Scenegraph is pretty snappy now, although there are plenty of opportunities left to optimize. Major changes:

* Added `TransformCache` class, which allows `ChainTransform` instances to be re-used across frames. This prevents most of the program recompiling.
* Canvas gets `ndc`, `framebuffer`, and `pixels` entities that are used to represent the coordinate systems it handles.
* Avoid generating throw-away `Variable` instances in `Function.__setitem__`. This was wasting a lot of time.

There is still some cleanup left to do, but once this is merged I think we finally have a usable scenegraph.
The original motivation was that it makes transform caching easier, because the key used for caching is `list(map(id, entities))`. Other benefits:

* Simpler to deal with the entire scenegraph chain being a stack of entities, rather than manually combining these transforms to the bottom of the chain.
* Eventually I'd like to allow the user to think more about coordinate systems rather than transformations, and for this we need a "handle" for each coordinate system (and that's exactly what an Entity is). So for example, imagine `map(my_data, from=self, to=canvas.pixels)`.