Reduce Memory Overhead With __slots__

The results of running a memory checking script (included in this PR) against the code in master and this branch show around 32% less memory is consumed when using `__slots__` vs. the standard per-instance dictionaries that each object has.

    # 10k Test objects (master)
    $ python check_mem.py
    baseline 33300 7400
    10k 258136 232324

    # 10k Test objects (slots)
    $ python check_mem.py
    baseline 33296 7416
    10k 183844 157884