Tag interface part 2: Better record added/removed tags in the tx log

Summary:
Added or removed tags now appear in the transaction log as revisions of the
Thread object.

[Stop reading here if you don't care about implementation details.]

Given related parent and child tables, we add the ability to record updates to
a parent's collection of children as a revision of the parent. See the
docstring in models/revision.py for details.

(Why not just have the TagItems association table subclass HasRevisions? you
may ask. Good question. One reason is that handling removed tags that way is
tricky, because all the transaction log can tell you is that a TagItem with
some ID was deleted. But you can't figure out from that what the corresponding
tag or thread was. Another reason is that delete transactions for the TagItem
table aren't created at all if you use an association proxy
(`thread.tags.remove(tag)`), because in this case sqlalchemy directly issues
sql to the database, without instantiating the association object.

Test Plan: Still working on the tests.

Reviewers: spang

Reviewed By: spang

Differential Revision: https://review.inboxapp.com/D160