Yeah, I was actually going to try to address that problem tomorrow, because it appears in various guises all over the place. I don't think it's manageable from an API perspective to solve this everywhere with dynamic checks in the API, just to handle the 1% case of users modifying attributes after construction. Note that sometimes it's even restrictive if, say, the user wants to change the `weight_solver` to a `decoder_solver`, but cannot because the change has to be made in a single transaction in order to keep the object in a valid state on every line (and then we would need to add a new method to swap solvers, which introduces more surface area to the API).

My idea was to write a `Validator` which takes a `Network` (formerly a `Model`), does all of the pre-build validation on it, and returns a verbose error structure. This would be used by `nengo_gui` and the `Builder` (pre-build time) to enforce all of the invariants that it currently assumes to hold implicitly. 

This idea was raised in #250, and I am excited to start reaping the benefits of such validation combined with the recent API simplifications. :smiley: 

What this means here, is that the check would be done in the constructor, and any errors caused by modifying attributes (after construction) would be raised when passed to the simulator. Then, I believe, if a specific build-time error is encountered more than 1% of the time, we can make that case a bit nicer for the user by adding some form of dynamic checking in the API. But this should be perceived as a design penalty for us, and so it's reasonable for us to feel that burden.

It may also be the case that there are certain classes of checks that we could easily enforce at the API level in a dynamic fashion, but I think the above step is first required in order to illuminate those possibilities, since we are currently not doing all of the checks that we need to be doing.