The cost of a short-lived read transaction is incredibly low, especially with Postgres. All the data for the last so many transactions will be in the database anyway until a vacuum happens. There's no CPU cost to read transactions that I'm aware of.
Explicit transaction blocks for single-statement reads are pointless. Extra packets for the transaction demarcation even more so.
The performance savings comes from the roundtrip latency of the BEGIN TRANSACTION / COMMIT packets.
"Wouldn't a good programming practice, be to ensure that everything that is supposed to be atomic, occur in a single, possibly large, SQL statement anyways?"
The simplistic answer to that question is a resounding yes.1) Code that depends on autocommit is hard to unit test, since you have to mock out whatever internal method autocommit calls
2) Code that depends on autocommit is hard to reason about, since you don't have a consistent view of your data, especially in multi-step update methods.
3) Because of 2, your updates will (not "may", "will definitely") be corrupted at some point, leaving broken bad data in the database. Comprehensive constraints help, but if you're relying on autocommit chances are you're not using constraints very well either.
2. autocommit is explicitly mentioned in terms of single select reads. Besides - if you use transactions in your update, it doesn't affect anything - postgres will do the right thing. Similarly, postgres will wrap single statement updates in transactions for you. Using it in multi-step procedures is a no-no - fortunately autocommit is per-connection, so if you are being careful about what connection you use, you can have both.
3. Another strawman - using autocommit for single selects doesn't preclude not using it for places where data integrity is a concern.