Add infrastructure to pypeline that allows containers to be notified
when they are being used last, this allows two things:
* `Pipe`s eagerly clearing those containers once they are done reading
their contents
* `ScheduledTask`s clearing those out at the end of their execution in
case the pipe did not do it
This overall should improve memory usage as container no longer take up
memory if they are no longer used as part of a `Schedule`.
In the same vein as `PureLLVMPassesPipe`, add a pipe to pypeline that
allows running arbitrarily-specified MLIR passes that do not depend on
the model.