André M. Happy to help!
COMMENT ON COLUMN replaces that table's catalog entry and bumps the database's catalog version, which leaves the client's cached catalog stale. The client rebuilds the full catalog every column write. With no multi column form, that's 20 rebuilds for 20 columns.
The transaction helps because in auto-commit, each statement needs a second round trip to fetch the new catalog. In a transaction the server sends it along with the statement itself which saves a roundtrip per comment. The rebuilds still happen per statement though, which is why you saw an improvement rather than it collapsing to a single commit.
For now, if you have persist_docs enabled, setting columns:false keeps your model-level descriptions while dropping one statement per column. If you want to keep column-level descriptions, scoping them to your marts and leaving them off staging may help:
docs.getdbt.com/reference/resource-configs/persist_docs
The rebuild cost should track the size of that database's catalog rather than the comment itself, so it'd help to know which database you benchmarked against and roughly how many tables it has.
Let me know if anything's unclear. I'll see what more we can do on our side and get back to you.