First off, what is the actual application? I highly doubt you need to do 10k raycasts. Generally if you invert the problem you can find new ways to solve it. (ie instead of can the camera see the objects, ask can the objects see the camera. You can then apply culling based on if the object is in the view frustrum etc. etc.)
Shadows are done using depth-buffer calculations, not raycasts (the geometry is mathematically projected onto a plane, and for each pixel, the depth is used to decide if it's in front or if if's behind). However, if you can represent your problem such that the answer can be determined by looking at what objects are visible to the pixels of a camera, then there is a solution using the rasterizer.
If each object has a unique color and is shadeless, and you perform a bge.texture.ImageRender() to generate a texture from a particular camera (any but the active camera), you can then sample it using list(texture.source.image), and then, using the color at a specified pixel, you can look up what object has that color. You could also sample the depth buffer by setting the camera into depth or zbuff mode (depth only if you have a floating-point texture that it's loading into).
This process can be automated somewhat. In one system I developed, I had to sample what object was clicked on when there were about 1 million polies. Having them all as physics objects added 5-6 seconds to program startup, and ran very slowly. So I did as described above, with the same auto-assigning unique colors at startup. I also used a shader that could flick between the 'uniqueID' mode and a 'display' mode such that by setting a uniform, the objects could be identified or display nicely.
Now you mention "Imagine a flash bomb in BGE, where I need to ray trace the path in all direction.". This could be represented by six cameras with a 90 degree field of view. Six cameras rendering at 512x512 does run at 60FPS with a million polygons - but it's a near thing. (GTX970, i7-6700)