I just spent an hour or so trying to figure out how to get the build-time shape of a graph operation. Had an issue ready to go and everything. It wasn't until I went poking around in the debugger that I realized it was on Output. I realize that there are design reasons to separate the output from the op, but asOutput() already exists, so I think having shape() and dataType() default methods on Operation that use asOutput is worth it from a usage and discovery standpoint.