As suggested by 'micycle' the R-Tree is matching my needs. With one call I create the index:
index = Index(generator(shapes))
where generator
yields the bboxes of supplied shapes.
And then I can do the intersection queries like:
intersections = index.intersection(bbox)
Thats it. Its fast for my needs (maybe because of compiled implementation). Factor 4 compared to brute force. (I don't have too many shapes.)