Confusion about calculate_group_id

I’m trying to send a group of transactions to two smart contracts, but calculate_group_id is not behaving as I would expect. Below is some code that sends two groups of transactions to the two contracts. The code below executes successfully, but if I move the first line of the for loop (txn_approve … ) outside of the for loop, the first iteration of the loop succeeds, but the second fails with an error (“incomplete group”)

Since the loop does not change txn_approve (except for setting its group id), I’m not sure why this is happening. My understanding is that calculate_group_id basically hashes the transactions, but in doing so, I assumed that it must ignore the group id). I think I must be missing something about how calculate_group_id works. Any help would be appreciated.

for asset_id in [assetA_id,assetB_id]:
    txn_approve = transaction.ApplicationNoOpTxn(creator_address,sp,app_id,app_args )

    txn_transfer = transaction.AssetTransferTxn(
        sender=stateless_contract_address,
        sp=params,
        receiver=receiver_address,
        amt=100,
        index=asset_id)

    gid = transaction.calculate_group_id( [txn_transfer,txn_approve] )
    txn_transfer.group = gid
    txn_approve.group = gid

    stx_transfer = transaction.LogicSigTransaction(txn_transfer, lsig)
    stx_approve = txn_approve.sign(creator_sk)

    txid = client.send_transactions([stx_transfer,stx_approve])