I was curious about this, so wrote something to check most of the use cases I could think of...
gist / execurl
The results are below:
##### current thread:
b'com.apple.root.default-qos.overcommit' <_MainThread(MainThread, started 1078071296)>
##### things running from a thread:
undecorated b'com.apple.root.default-qos.overcommit' <Thread(Thread-25, started 1085984768)>
on_main_thread b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
animated b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
animatcompletion b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
delayed b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
in_background b'com.apple.root.default-qos.overcommit' <_MainThread(MainThread, started 1078071296)>
##### Called from UI (press each button)
update b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
0
undecorated b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
1
on_main_thread b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
2
in_background b'com.apple.root.default-qos.overcommit' <_MainThread(MainThread, started 1078071296)>
3
delayed b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
4
animated b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
animatcompletion b'com.apple.main-thread' <_DummyThread(Dummy-1, started daemon 994000896)>
Basicaly, ui things, including actions/callbacks/update, and things decorated with on_main_thread are run on what ios calls main-thread queue, which is called the Dummy-1 by Python.
ui.in_background gets called on the python MainThread (main interpreter thread), from the standard dispatch queue.
Everything else is run on the standard queue also, but in whatever python thread called it - so either a threading.Thread or MainThread (main interpreter thread).
I don't really understand how threads work with the GCD dispatch queues, but the bottom line seems to be that ui.in_background items only get executed on the python interpreter main thread after the script has ended (so some care has to be used with in_background, since it might not run if your main script is doing other work, or sleeping, etc)