Why is such a large int (uint32) used for the transaction version field
What was the rational for using such a large integer?


Because Satoshi did not care about it. Bitcoin transaction serialization is not optimized for size. 


  Could this be reduced with a new block version?


No


  Could this be done without a hard fork?


No. But you can implement new way to serialize data on disk and on network and encode/decode transaction contents on-the-fly. In fact nobody cares about these bytes.